package com.xy.job.executor.springboot

import com.xy.job.executor.config.AdminProperties
import com.xy.job.executor.config.ExecutorProperties
import com.xy.job.executor.core.client.DefaultAdminClient
import com.xy.job.executor.core.client.IAdminClient
import com.xy.job.executor.core.job.IJobHandler
import com.xy.job.executor.core.job.JobHandlerRegistry
import com.xy.job.executor.core.server.EmbedServer
import com.xy.job.executor.core.server.ExecutorServiceBiz
import com.xy.job.executor.core.server.RegisterThread
import org.springframework.beans.factory.config.BeanPostProcessor
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration


@Configuration
internal open class ExecutorAutoConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "xy-job.admin")
    open fun adminProperties(): AdminProperties {
        return AdminProperties()
    }

    @Bean
    @ConfigurationProperties(prefix = "xy-job.executor")
    open fun executorProperties(): ExecutorProperties {
        return ExecutorProperties()
    }

    @Bean
    open fun adminClient(adminProperties: AdminProperties): IAdminClient {
        return DefaultAdminClient(
            adminHost = adminProperties.host,
            adminPort = adminProperties.port.toInt(),
        )
    }

    @Bean
    open fun executorServiceBiz(adminClient: IAdminClient): ExecutorServiceBiz {
        return ExecutorServiceBiz(adminClient)
    }

    @Bean
    open fun registerThread(
        adminClient: IAdminClient,
        executorProperties: ExecutorProperties
    ): RegisterThread {
        val registerThread = RegisterThread(
            adminClient = adminClient,
            executorProperties = executorProperties,
        )
        registerThread.start()
        return registerThread
    }

    @Bean(initMethod = "start", destroyMethod = "stop")
    open fun embeddedServer(
        executorProperties: ExecutorProperties,
        executorServiceBiz: ExecutorServiceBiz,
    ): EmbedServer {
        return EmbedServer(
            port = executorProperties.port.toInt(),
            executorServiceBiz = executorServiceBiz
        )
    }

    @Bean
    open fun jobHandlerProcessor(): BeanPostProcessor {
        return object : BeanPostProcessor {
            override fun postProcessAfterInitialization(bean: Any, beanName: String): Any {
                if (bean is IJobHandler) {
                    JobHandlerRegistry.register(bean::class.qualifiedName!!, bean)
                }
                return bean
            }
        }
    }

}